package org.dreamwork.jasmine2.restful.client.gui.model;

import org.dreamwork.jasmine2.restful.APIDefinition;
import org.dreamwork.jasmine2.restful.APIParameterDefinition;
import org.dreamwork.jasmine2.restful.ContextParameterDefinition;
import org.dreamwork.jasmine2.restful.MethodDefinition;

import javax.swing.table.DefaultTableModel;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: seth.yang
 * Date: 2014/12/10
 * Time: 2:47
 */
public class ParameterTableModel extends DefaultTableModel {
    private List<String> names;
    private Map<String, ParameterHolder> holders;

    private static final String[] COLUMN_NAMES = {"Name", "Type", "Value"};

    public ParameterTableModel (APIDefinition api, MethodDefinition method) {
        this (api, method, false);
    }

    public ParameterTableModel (APIDefinition api, MethodDefinition method, boolean isContext) {
        names = new ArrayList<String> ();
        holders = new HashMap<String, ParameterHolder> ();
        if (isContext) {
            Collection<ContextParameterDefinition> c = api.getContextParameters ();
            for (ContextParameterDefinition cpd : c) {
                if (!"javax.servlet.ServletContext".equals (cpd.getTypeName ())) {
                    names.add (cpd.getName ());
                    holders.put (cpd.getName (), new ParameterHolder (cpd.getName (), cpd.getTypeName (), cpd.isRequired ()));
                }
            }
            c = method.getContextParameters ();
            for (ContextParameterDefinition cpd : c) {
                if (!"javax.servlet.ServletContext".equals (cpd.getTypeName ())) {
                    if (!names.contains (cpd.getName ()))
                        names.add (cpd.getName ());
                    holders.put (cpd.getName (), new ParameterHolder (cpd.getName (), cpd.getTypeName (), cpd.isRequired ()));
                }
            }
        } else {
            Collection<APIParameterDefinition> cc = method.getParameters ();
            for (APIParameterDefinition pd : cc) {
                if (!names.contains (pd.getName ()))
                    names.add (pd.getName ());
                holders.put (pd.getName (), new ParameterHolder (pd.getName (), pd.getClassName ()));
            }
        }
        Collections.sort (names);
    }

    @Override
    public int getRowCount () {
        return names == null ? super.getRowCount () : names.size ();
    }

    @Override
    public int getColumnCount () {
        return 3;
    }

    @Override
    public String getColumnName (int column) {
        return COLUMN_NAMES [column];
    }

    @Override
    public boolean isCellEditable (int row, int column) {
        return column == 2;
    }

    @Override
    public Object getValueAt (int row, int column) {
        if (names == null || names.isEmpty ())
            return null;

        String key = names.get (row);
        ParameterHolder holder = holders.get (key);
        switch (column) {
            case 1 : return holder.getType ();
            case 2 : return holder.getValue ();
            default: return key;
        }
    }

    @Override
    public void setValueAt (Object value, int row, int column) {
        if (column == 2) {
            String key = names.get (row);
            ParameterHolder holder = holders.get (key);
            holder.setValue (value);
        }
    }

    public String getValueType (int row) {
        String name = names.get (row);
        ParameterHolder holder = holders.get (name);
        return holder.getType ();
    }

    public Map<String, ParameterHolder> getParameters () {
        return holders;
    }

    public String checkParameters () {
        for (ParameterHolder holder : holders.values ()) {
            if (holder.isRequire () && holder.getValue () == null) {
                return "Parameter [" + holder.getName () + "] is required.";
            }
        }
        return null;
    }

    public void setData (Map<String, ParameterHolder> holders) {
        if (holders == null) return;
        if (this.holders == null) {
            this.holders = holders;
            names = new ArrayList<String> ();
            names.addAll (holders.keySet ());
        } else {
            this.holders.putAll (holders);
        }

        Collections.sort (names);
        fireTableDataChanged ();
    }
}